/** 
 *  @file
 *  @brief   剪切单元
 *  @author  yuanchenxi
 *  @date    2024.04.23
 *  @version v1.0
 *  @par Copyright(c):  ShenGong  Simulation corporation
 */

#pragma once
#include "Utility/Algebra/Matrix.h"
#include "Utility/Algebra/Point.h"
#include "DataStructure/Common/Out.h"
#include "DataStructure/Input/Material/IsotropicMaterial.h"
#include "DataStructure/Input/Property/PSHEARData.h"
#include "DataStructure/Result/ElementalForce/SHEARForceData.h"
#include "DataStructure/Result/ElementalStress/SHEARStressData.h"
#include "../Interface/IElementCalculator.h"

SG_FEMSOLVER_ELEMENT_NAMESPACE_OPEN

/** @brief 剪切单元矩阵计算器
 */
class ElementCalculator_DECLSPEC ShearElementCalculator : public SG::FEMSolver::Element::IElementCalculator
{
public:
    ShearElementCalculator() = default;
    virtual ~ShearElementCalculator() = default;

    /** @brief 计算坐标转换阵
     * 
     * 节点1,3方向矢量和 节点2，4矢量的叉乘做为坐标系的Z轴， 1-2节点间矢量往垂直z轴方向投影做为坐标系Z轴
     * @param [in]  points            节点全局坐标
     * @param [out] Tel               坐标转换阵
     * @param [out] localPoints       单元坐标系下，节点局部坐标
     * @param [out] area              单元面积
     */
    void ComputeCoordTrans 
    (
    const SG::Algebra::PointArray&        points,
    SG::Algebra::Matrixd& _OUT            Tel,
    SG::Algebra::PointArray& _OUT         localPoints,
    SG::DataStructure::Common::Real& _OUT area,
    SG::DataStructure::Common::Real& _OUT warp
    ) const;


    /** @brief 应变能计算
     * @param [in]  localPoints       单元局部坐标
     * @param [in]  area              单元面积
     * @param [in]  G                 剪切模量
     * @param [in]  property          截面属性
     * @param [in]  mu                弹性模量
     * @param [out] PArray       P数组
     * return  adaptability      单元应变能
     */
    SG::DataStructure::Common::Real computeAdaptability
    (
    const SG::Algebra::PointArray&           localPoints,
    const SG::DataStructure::Common::Real    area,
    const SG::DataStructure::Common::Real    G,
    const SG::DataStructure::FEM::PSHEARData& property,
    const SG::DataStructure::Common::Real    mu,
    SG::DataStructure::Common::Real*  const   PArray
    ) const;
    
    /** @brief 计算单元刚度矩阵
     * @param [in]  localPoints  单元局部坐标
     * @param [in]  adaptibility 单元应变能
     * @param [in]  area         单元面积
     * @param [in]  E            弹性模量
     * @param [in]  property     截面属性
     * @param [out] Kel          单元全局坐标下刚度矩阵
     */
    void ComputeStiffness 
    (
    const SG::Algebra::PointArray&            localPoints,
    const SG::DataStructure::Common::Real     adaptability,
    const SG::DataStructure::Common::Real     area,
    const SG::DataStructure::Common::Real     E,
    const SG::DataStructure::FEM::PSHEARData& property,
    SG::Algebra::Matrixd& _OUT                Kel
    ) const;

    /** @brief 计算单元质量矩阵
     * @param [in]  localPoints  单元局部坐标
     * @param [in]  rho          密度
     * @param [in]  property     截面属性
     * @param [out] Mass         单元局部坐标下质量矩阵
     */
    void ComputeMass 
    (
    const SG::Algebra::PointArray&            localPoints,
    const SG::DataStructure::Common::Real&    rho,
    const SG::DataStructure::FEM::PSHEARData& property,
    SG::Algebra::Matrixd& _OUT                Mass
    ) const; 

    void ComputeElementForceAndStress 
    (
    const SG::Algebra::PointArray&                      localPoints,
    const SG::DataStructure::FEM::PSHEARData&           property,
    const SG::DataStructure::FEM::IsotropicMaterial&    material,
    SG::DataStructure::Common::Real                     area,
    SG::DataStructure::Common::Real                     warp,
    SG::Algebra::Matrixd&                               eleDisp,
    SG::Algebra::Matrixd&                               Tel23,
    SG::DataStructure::Post::SHEARForceData& _OUT       eleForceData,
    SG::DataStructure::Post::SHEARStressData& _OUT      eleStressData
    ) const; 

    virtual void Initialize (SG::DataStructure::FEM::ElementTypes type) override;
    virtual void ComputeElementMatries (const SG::DBManager::DBServiceFactorySP dbServiceFactory) override;
    virtual void DataRecovery(const SG::DBManager::DBServiceFactorySP dbServiceFactory, int subcaseId, SG::DataStructure::Common::Real time, const std::vector<SG::DataStructure::Common::Real>& globalDisplacement) override;
    virtual void ComputeStressStiffness (const SG::DBManager::DBServiceFactorySP dbServiceFactory, int staticSubId) override;
    static ElementCalculatorSP Create() {return std::make_shared<ShearElementCalculator>();}
private:
    SG::DataStructure::FEM::ElementTypes m_type;
};

SG_FEMSOLVER_ELEMENT_NAMESPACE_CLOSE